#ifndef __DATABASE_ADT_H__
#define __DATABASE_ADT_H__

#include "../../common/queueADT/queueADT.h"

#define FALSE   0
#define TRUE    !FALSE

/** Timeout values on busy or lock conditions   **/
/** if you observe lock errors you might try to **/
/** increase the values. **/
/** SQLTM_COUNT*SQLTM_TIME micro seg timeout **/
#define SQLTM_COUNT       500
#define SQLTM_TIME        1000


typedef struct databaseCDT *databaseADT;

typedef enum { DB_SUCCESS = 0, DB_INVALID_ARG, DB_NO_MATCH, DB_NO_MEMORY,
               DB_INTERNAL_ERROR, DB_ACCESS_DENIED, DB_ALREADY_EXISTS,
               DB_NO_SLOTS } DB_ERR;


/**
 * Creates a new database instance.
 *
 * @param[out]  db      Pointer to the newly created database instance.
 * @param[in]   dbFile  Path to the database file.
 * @param[in]   errLog  The stream to which to output error logs.
 *                      If NULL error log is disabled.
 *
 * @return      DB_SUCCESS if the operation succeded, an appropiate error
 *              code otherwise.
*/
DB_ERR NewDatabaseADT( databaseADT *db, const char *dbFile, FILE *errLog );

/**
 * Destroys a database instance.
 *
 * @param[in]   db      Database instance to be destroyed.
*/
void FreeDatabaseADT( databaseADT db );

/**
 * Creates all database tables if they don't exist already.
 *
 * @param[in]   db      The database into which to attempt to
 *                      create the tables.
 * @param[in]   schema  Path to the db schema.
 *
 * @return      DB_SUCCESS if the operation succeded, an appropiate error
 *              code otherwise.
*/
DB_ERR DBBuildDatabase( databaseADT db, const char *schema );

/**
 * Adds a user to the db.
 *
 * @param[in]   db   Pointer to the newly created database instance.
 * @param[in]   user char *.
 * @param[in]   fifo char *.
 *
 * @return      DB_SUCCESS if the operation succeded, an appropiate error
 *              code otherwise.
*/
DB_ERR DBaddUser(databaseADT db, const char *user, const char *fifo);

/**
 * Adds a dir to the db.
 *
 * @param[in]   db   Pointer to the newly created database instance.
 * @param[in]   dir  char *.
 *
 * @return      DB_SUCCESS if the operation succeded, an appropiate error
 *              code otherwise.
*/
DB_ERR DBaddDir(databaseADT db, const char *dir);

/**
 * Gets the user list.
 *
 * @param[in]   db          Pointer to the newly created database instance.
 * @param[out]  queue       QueueADT.
 *
 * @return      DB_SUCCESS if the operation succeded, an appropiate error
 *              code otherwise.
*/
DB_ERR DBgetUserQueue(databaseADT db, queueADT queue);

DB_ERR DBgetFifos(databaseADT db, queueADT queue);

/**
 * Disconnect an user
 *
 * @param[in]   db          Pointer to the newly created database instance.
 * @param[out]  use         char *
 *
 * @return      DB_SUCCESS if the operation succeded, an appropiate error
 *              code otherwise.
*/
DB_ERR DBdisconnectUser(databaseADT db, const char *user);

/**
 * Deletes all entries from online table.
 *
 * @param[in]   db          Pointer to the newly created database instance.
 *
 * @return      DB_SUCCESS if the operation succeded, an appropiate error
 *              code otherwise.
*/
DB_ERR DBdeleteOnline(databaseADT db);

/**
 * Disconnects an user by his/hers fifo.
 *
 * @param[in]   db          Pointer to the newly created database instance.
 * @param[out]  fifo        char *
 *
 * @return      DB_SUCCESS if the operation succeded, an appropiate error
 *              code otherwise.
*/
DB_ERR DBdisconnectFifo(databaseADT db, const char *fifo);

/**
 * Removes user from dir sync by his/hers fifo.
 *
 * @param[in]   db          Pointer to the newly created database instance.
 * @param[in]   fifo        char *
 * @param[in]   dir         char *
 *
 * @return      DB_SUCCESS if the operation succeded, an appropiate error
 *              code otherwise.
*/
DB_ERR DBremoveDirByFifo(databaseADT db, const char *fifo, const char *dir);

/**
 * Adds into users_per_dir tuple by FIFO and dirname.
 *
 * @param[in]   db          Pointer to the newly created database instance.
 * @param[out]  fifo        char *
 * @param[out]  dir         char *
 *
 * @return      DB_SUCCESS if the operation succeded, an appropiate error
 *              code otherwise.
*/
DB_ERR DBaddFifoDir(databaseADT db, const char *fifo, const char *dir);

/**
 * Gets the fifo list related to a dir.
 *
 * @param[in]   db          Pointer to the newly created database instance.
 * @param[out]  queue       QueueADT.
 * @param[in]   fifo        char *
 * @param[in]   dir         char *
 *
 * @return      DB_SUCCESS if the operation succeded, an appropiate error
 *              code otherwise.
*/
DB_ERR DBgetUpdateQueue(databaseADT db, queueADT queue, const char *fifo, const char *dir);

/**
 * Gets the user's id list related to a dir.
 *
 * @param[in]   db          Pointer to the newly created database instance.
 * @param[out]  queue       QueueADT.
 * @param[in]   id          int
 * @param[in]   dir         char *
 *
 * @return      DB_SUCCESS if the operation succeded, an appropiate error
 *              code otherwise.
*/
DB_ERR DBgetUpdateIDs(databaseADT db, queueADT queue, const int id, const char *dir);

/**
 * Gets last 10 actions from a user.
 *
 * @param[in]   db          Pointer to the newly created database instance.
 * @param[out]  queue       QueueADT.
 * @param[in]   user        char *
 *
 * @return      DB_SUCCESS if the operation succeded, an appropiate error
 *              code otherwise.
*/
DB_ERR DBgetLast10User(databaseADT db, queueADT queue, char *user);

/**
 * Gets last 10 actions from every user.
 *
 * @param[in]   db          Pointer to the newly created database instance.
 * @param[out]  queue       QueueADT.
 *
 * @return      DB_SUCCESS if the operation succeded, an appropiate error
 *              code otherwise.
*/
DB_ERR DBgetLast10(databaseADT db, queueADT queue);

/**
 * Logs an action by a user.
 *
 * @param[in]   db          Pointer to the newly created database instance.
 * @param[out]  queue       QueueADT.
 * @param[in]   user        char *
 * @param[in]   action      char *
 * @return      DB_SUCCESS if the operation succeded, an appropiate error
 *              code otherwise.
*/
DB_ERR DBaddLog(databaseADT db, const char *fifo, const char *action);
DB_ERR DBaddLogSM(databaseADT db, const char *fifo, const char *action);
/**
 * Gets the id of a user.
 *
 * @param[in]   db          Pointer to the newly created database instance.
 * @param[in]   user        char *
 * @param[out]  id          int *
 * @return      DB_SUCCESS if the operation succeded, an appropiate error
 *              code otherwise.
*/
DB_ERR DBgetUserID(databaseADT db, const char *user, int *id);

/**
 * See if a user is online.
 *
 * @param[in]   db          Pointer to the newly created database instance.
 * @param[in]   user        char *
 * @param[out]  online      int *
 * @return      DB_SUCCESS if the operation succeded, an appropiate error
 *              code otherwise.
*/
DB_ERR DBisOnline(databaseADT db, const char *user, int *online);

/**
 * Gets used ids from online.
 *
 * @param[in]   db          Pointer to the newly created database instance.
 * @param[out]  queue       QueueADT.
 * @return      DB_SUCCESS if the operation succeded, an appropiate error
 *              code otherwise.
*/
DB_ERR DBgetUsedOnline(databaseADT db, queueADT queue);

/**
 * Gets user's synced dirs.
 *
 * @param[in]   db          Pointer to the newly created database instance.
 * @param[out]  queue       QueueADT.
 * @param[in]   user        char *
 * @return      DB_SUCCESS if the operation succeded, an appropiate error
 *              code otherwise.
*/
DB_ERR DBgetDirPerUserQueue(databaseADT db, queueADT queue, const char *user);

/**
 * Inserts data into online.
 *
 * @param[in]   db          Pointer to the newly created database instance.
 * @param[in]   id          int.
 * @param[in]   user        char *
 * @param[in]   used        int.
 * @return      DB_SUCCESS if the operation succeded, an appropiate error
 *              code otherwise.
*/
DB_ERR DBinsertOnline(databaseADT db, const int id, const char *user, const int used);

/**
 * Inserts data into online.
 *
 * @param[in]   db          Pointer to the newly created database instance.
 * @param[in]   old_id      int.
 * @param[in]   id          int.
 * @param[in]   user        char *
 * @param[in]   used        int.
 * @return      DB_SUCCESS if the operation succeded, an appropiate error
 *              code otherwise.
*/
DB_ERR DBmodifOnline(databaseADT db, const int old_id, const int id, const char *user, const int used);

/**
 * Gets first free ID on online data into online.
 *
 * @param[in]   db          Pointer to the newly created database instance.
 * @param[out]  id          int.
 * @param[in]   user        char *
 * @return      DB_SUCCESS if the operation succeded, an appropiate error
 *              code otherwise.
*/
DB_ERR DBgetOnlineFreeID(databaseADT db, int *id, const char *user);
DB_ERR DBmodifyOnline(databaseADT db, const int old_id, const int id, const char *user, const int used);
DB_ERR DBgetDirQueue(databaseADT db, queueADT queue);
DB_ERR DBisFreeOnline(databaseADT db, int *bool, const int id);
DB_ERR DBisSynched(databaseADT db, int *sync, const int id, const char *dir);

DB_ERR DBgetUserIDPI(databaseADT db, const char *fifo, int *id);

#endif
